home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1995 #5 & #6 / Amiga Plus CD - 1995 - No. 5 and 6.iso / pd / packer / mcvert / unpack.c < prev   
C/C++ Source or Header  |  1991-11-16  |  7KB  |  193 lines

  1. #include "mactypes.h"
  2.  
  3. extern word magic[];
  4. extern FILE *output;
  5. extern char *dir, *ext;
  6.  
  7. ulong pit_datalen, pit_rsrclen;
  8. word hqx_crc, write_pit_fork(); 
  9. char pitfname[BINNAMELEN];              /* name of file being unpacked */
  10. FILE *pitfile;                          /* output file */
  11.  
  12. branch branchlist[255], *branchptr, *read_tree();
  13. leaf leaflist[256], *leafptr;
  14. word Huff_nibble, Huff_bit_count;
  15. byte (*read_char)(), get_crc_byte(), getHuffbyte();
  16.  
  17. word un_pit()
  18. {   char PitId[4];
  19.     int i;
  20.     word pit_crc;
  21.  
  22.     hqx_crc = 0;
  23.     /* Read and unpack until the PackIt End message is read */
  24.     for (;;) {
  25.         read_char = get_crc_byte;
  26.         for (i = 0; i < 4; i++) PitId[i] = (char) get_crc_byte();
  27.         if (!strncmp(PitId, "PEnd", 4)) break;
  28.  
  29.         if (strncmp(PitId, "PMag", 4) && strncmp(PitId, "PMa4", 4))
  30.             error("Unrecognized Packit format message %s", PitId);
  31.  
  32.         if (PitId[3] == '4') {          /* if this file is compressed */
  33.             branchptr = branchlist;     /* read the Huffman decoding  */
  34.             leafptr = leaflist;         /* tree that is on the input  */
  35.             Huff_bit_count = 0;         /* and use Huffman decoding   */
  36.             read_tree();                /* subsequently               */
  37.             read_char = getHuffbyte;
  38.             }
  39.  
  40.         read_pit_hdr();     /* also calculates datalen, rsrclen,
  41.                                pitfile, pitfname */
  42.         pit_crc = write_pit_fork(pit_datalen, 0);
  43.         pit_crc = write_pit_fork(pit_rsrclen, pit_crc);
  44.         check_pit_crc(pit_crc, "  File data/rsrc CRC mismatch in %s", pitfname);
  45.         fclose(pitfile);
  46.         }
  47.     hqx_crc = (hqx_crc << 8) ^ magic[hqx_crc >> 8];
  48.     hqx_crc = (hqx_crc << 8) ^ magic[hqx_crc >> 8];
  49.     return hqx_crc;
  50.     }
  51.  
  52. check_pit_crc(calc_crc, msg, name)
  53. word calc_crc;
  54. char msg[], name[];
  55. {   word read_crc;
  56.     read_crc = (*read_char)() << 8;
  57.     read_crc |= (*read_char)();
  58.     if (read_crc != calc_crc) error(msg, name);
  59.     }
  60.  
  61. /* This routine reads the header of a packed file and appropriately twiddles it,
  62.     determines if it has CRC problems, creates the .bin file, and puts the info
  63.     into the .bin file.
  64.     Output is pit_datalen, pit_rsrclen, pitfname, pitfile */
  65. read_pit_hdr()
  66. {   register int n;
  67.     register byte *pit_byte;
  68.     register ulong pit_crc;
  69.     pit_header pit;
  70.     info_header info;
  71.     short crc;
  72.  
  73.     extern short calc_mb_crc();
  74.     /* read the pit header and compute the CRC */
  75.     pit_crc = 0;
  76.     pit_byte = (byte *) &pit;
  77.     for (n = 0; n < sizeof(pit_header); n++) {
  78.         *pit_byte = (*read_char)();
  79.         pit_crc = ((pit_crc & 0xff) << 8)
  80.                     ^ magic[*pit_byte++ ^ (pit_crc >> 8)];
  81.         }
  82.  
  83.     /* stuff the pit header data into the info header */
  84.     bzero(&info, sizeof(info_header));
  85.     info.nlen = pit.nlen;
  86.     strncpy(info.name, pit.name, pit.nlen);     /* name */
  87.     bcopy(pit.type, info.type, 9);              /* type, author, flag */
  88.     bcopy(pit.dlen, info.dlen, 16);             /* (d,r)len, (c,m)tim */
  89.     info.flags  &= 0x7e;                        /* reset lock bit, init bit */
  90.     if (pit.protect & 0x40) info.protect = 1;   /* copy protect bit */
  91.     info.uploadvers = '\201';
  92.     info.readvers = '\201';
  93.  
  94.     /* calculate MacBinary CRC */
  95.     crc = calc_mb_crc(&info, 124, 0);
  96.     info.crc[0] = (char) (crc >> 8);
  97.     info.crc[1] = (char) crc;
  98.  
  99.     /* Create the .bin file and write the info to it */
  100.     pit.name[pit.nlen] = '\0';
  101.     unixify(pit.name);
  102.     sprintf(pitfname, "%s/%s%s", dir, pit.name, ext);
  103.     fprintf(output,
  104.         " %-14s%-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  105.         (read_char == get_crc_byte) ? "Unpacking" : "Decompressing",
  106.         pit.name, pit.type, pit.auth);
  107.     if ((pitfile = fopen(pitfname, "w")) == NULL)
  108.         error("  Cannot open %s", pitfname);
  109.     check_pit_crc(pit_crc, "  File header CRC mismatch in %s", pitfname);
  110.     fwrite(&info, sizeof(info_header), 1, pitfile);
  111.  
  112.     /* Get a couple of items we'll need later */
  113.     bcopy(pit.dlen, &pit_datalen, 4);
  114.     pit_datalen = mac2long(pit_datalen);
  115.     bcopy(pit.rlen, &pit_rsrclen, 4);
  116.     pit_rsrclen = mac2long(pit_rsrclen);
  117.     }
  118.  
  119. /* This routine copies bytes from the decoded input stream to the output
  120.     and calculates the CRC.  It also pads to a multiple of 128 bytes on the
  121.     output, which is part of the .bin format */
  122. word write_pit_fork(nbytes, calc_crc)
  123. register ulong nbytes;
  124. register ulong calc_crc;
  125. {   register ulong b;
  126.     int extra_bytes;
  127.  
  128.     extra_bytes = 127 - (nbytes+127)%128; /* pad fork to mult of 128 bytes */
  129.     while (nbytes--) {
  130.         b = (*read_char)();
  131.         calc_crc = ((calc_crc & 0xff) << 8) ^ magic[b ^ (calc_crc >> 8)];
  132.         putc(b, pitfile);
  133.         }
  134.     while (extra_bytes--) putc(0, pitfile);
  135.     return (word) calc_crc;
  136.     }
  137.  
  138. /* This routine recursively reads the compression decoding data.
  139.    It appears to be Huffman compression.  Every leaf is represented
  140.    by a 1 bit, then the byte it represents.  A branch is represented
  141.    by a 0 bit, then its zero and one sons */
  142. branch *read_tree()
  143. {   register branch *branchp;
  144.     register leaf *leafp;
  145.     register ulong b;
  146.     if (!Huff_bit_count--) {
  147.         Huff_nibble = get_crc_byte();
  148.         Huff_bit_count = 7;
  149.         }
  150.     if ((Huff_nibble<<=1) & 0x0100) {
  151.         leafp = leafptr++;
  152.         leafp->flag = 1;
  153.         b = get_crc_byte();
  154.         leafp->data = Huff_nibble | (b >> Huff_bit_count);
  155.         Huff_nibble = b << (8 - Huff_bit_count);
  156.         return (branch *) leafp;
  157.         }
  158.     else {
  159.         branchp = branchptr++;
  160.         branchp->flag = 0;
  161.         branchp->zero = read_tree();
  162.         branchp->one  = read_tree();
  163.         return branchp;
  164.         }
  165.     }
  166.  
  167. /* This routine returns the next 8 bits.  It finds the byte in the
  168.    Huffman decoding tree based on the bits from the input stream. */
  169. byte getHuffbyte()
  170. {   register branch *branchp;
  171.     branchp = branchlist;
  172.     while (!branchp->flag) {
  173.         if (!Huff_bit_count--) {
  174.             Huff_nibble = get_crc_byte();
  175.             Huff_bit_count = 7;
  176.             }
  177.         branchp = ((Huff_nibble<<=1) & 0x0100) ? branchp->one : branchp->zero;
  178.         }
  179.     return ((leaf *) branchp)->data;
  180.     }
  181.  
  182. /* This routine returns the next byte on the .hqx input stream, hiding
  183.     most file system details at a lower level.  .hqx CRC is maintained
  184.     here */
  185. byte get_crc_byte()
  186. {   register ulong c;
  187.     extern byte *buf_ptr, *buf_end;
  188.     if (buf_ptr == buf_end) fill_hqxbuf();
  189.     c = *buf_ptr++;
  190.     hqx_crc = ((hqx_crc << 8) | c) ^ magic[hqx_crc >> 8];
  191.     return (byte) c;
  192.     }
  193.